
/**
 * @en  Utility class for reading the data sent to the SideChannel.
 * @zh 用于读取发送到侧通道的数据的实用程序类。
 */
export class IncomingMessage {
    private _data: Uint8Array;
    private _view: DataView;
    private _offset: number = 0;


    constructor(data: Uint8Array) {
        this._data = data;
        this._view = new DataView(data.buffer);
    }

    /**
     * 从流中读取一个布尔值，并返回值
     * @param defaultValue 
     */
    public readBoolean(defaultValue: boolean = false): boolean {

        if (!this.canReadMore()) {
            return defaultValue;
        }

        const value = this._view.getUint8(this._offset);
        const booleanValue = Boolean(value);
        this._offset += 1;
        return booleanValue;
    }

    public readInt32(defaultValue: number = 0): number {
        if (!this.canReadMore()) {
            return defaultValue;
        }
        const intValue = this._view.getInt32(this._offset, true);
        this._offset += 4;

        return intValue;

    }

    public readFloat32(defaultValue: number = 0.0): number {
        const value = this._view.getFloat32(this._offset, true);
        if (!this.canReadMore()) {
            return defaultValue
        }
        return value;

    }

    public readString(defaultValue: string = ""): string {
        if (!this.canReadMore()) {
            return defaultValue;
        }

        const strLength = this.readInt32();
        const strBytes = new Uint8Array(this._data.buffer, this._offset, strLength);
        this._offset += strLength;
        return new TextDecoder().decode(strBytes);
    }

    /**
     * @en Reads a list of floats from the message. The length of the list is stored in the message.
     * @zh 从消息中读取一个浮点数列表。列表的长度存储在消息中。
     * @param defaultValue 
     * @returns 
     */
    public readFloatList(defaultValue: number[] = []): number[] {
        if (!this.canReadMore()) {
            return defaultValue;
        }
        const len = this.readInt32();
        const output: number[] = [];
        for (let i = 0; i < len; i++) {
            const float32Value = this.readFloat32();
            output.push(float32Value);
        }
        return output;
    }

    /**
     * @en Gets the original data of the message. Note that this will return all of the data, even if part of it has already been read.
     * @zh 获取消息的原始数据。请注意，这将返回所有数据，即使其中的一部分已经被读取。
     * @returns 返回原始字节数组
     */
    public getRawBytes(): Uint8Array {
        return this._data;
    }


    private canReadMore(): boolean {
        return this._offset < this._data.byteLength;
    }
}